package com.melodyframe.stage.supports.freemarker;

import java.io.IOException;
import java.io.StringWriter;

import com.melodyframe.common.context.Context;
import com.melodyframe.stage.core.Stage;
import com.melodyframe.stage.core.StageAware;
import com.melodyframe.stage.core.renderer.View;
import com.melodyframe.stage.core.renderer.ViewRenderer;
import com.melodyframe.stage.supports.freemarker.directive.StageDirective;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class FreemarkerViewRenderer implements ViewRenderer, StageAware {

	private Stage			stage;
	private Configuration	freemarkerCfg;
	private boolean			inited;
	private StageDirective	stageDirective;

	public void prepare() {
		if (!this.inited) {
			synchronized (this) {
				if (!this.inited) {
					if (null == this.freemarkerCfg) {
						this.freemarkerCfg = new Configuration();
						this.freemarkerCfg.setClassForTemplateLoading(
								this.getClass(), "/templates");
					}
					if (null == this.stageDirective) {
						this.stageDirective = new StageDirective(this.stage);
					}
					freemarkerCfg.setSharedVariable("stage",
							this.stageDirective);
					this.inited = true;
				}
			}
		}
	}

	@Override
	public View render(String name, Context context) {
		this.prepare();
		View view = new View();
		try {
			StringWriter out = new StringWriter();
			Template temp = freemarkerCfg.getTemplate(name + ".ftl");
			temp.process(context, out);
			view.setResponseText(out.toString());
			return view;
		} catch (IOException e) {
			e.printStackTrace();
		} catch (TemplateException e) {
		}
		return null;
	}

	public Stage getStage() {
		return stage;
	}

	@Override
	public void setStage(Stage stage) {
		this.stage = stage;
	}

	public Configuration getFreemarkerCfg() {
		return freemarkerCfg;
	}

	public void setFreemarkerCfg(Configuration freemarkerCfg) {
		this.freemarkerCfg = freemarkerCfg;
	}

	public StageDirective getStageDirective() {
		return stageDirective;
	}

	public void setStageDirective(StageDirective stageDirective) {
		this.stageDirective = stageDirective;
	}

}
